import logging
import sys
from datetime import datetime

from colorlog import ColoredFormatter
from fastapi import Request, Response
from pythonjsonlogger import jsonlogger
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint

from app.core.config import settings


class RequestIDFilter(logging.Filter):
    """添加请求ID到日志记录"""
    def filter(self, record: logging.LogRecord) -> bool:
        record.request_id = getattr(record, 'request_id', 'N/A')
        return True


def setup_logger():
    """配置日志系统"""
    logger = logging.getLogger()
    logger.setLevel(settings.LOG_LEVEL)
    logger.handlers.clear()  # 清除默认处理器
    
    # 日志格式
    log_format = (
        '%(asctime)s - %(request_id)s - %(name)s - %(levelname)s - %(message)s'
    )
    
    # 颜色格式
    color_format = (
        '%(log_color)s%(asctime)s - %(request_id)s - %(name)s - %(levelname)s - %(message)s%(reset)s'
    )
    
    # 控制台处理器
    console_handler = logging.StreamHandler(sys.stdout)
    console_formatter = ColoredFormatter(
        color_format,
        datefmt='%Y-%m-%d %H:%M:%S',
        log_colors={
            'DEBUG': 'cyan',
            'INFO': 'green',
            'WARNING': 'yellow',
            'ERROR': 'red',
            'CRITICAL': 'red,bg_white',
        }
    )
    console_handler.setFormatter(console_formatter)
    console_handler.addFilter(RequestIDFilter())
    
    # 文件处理器
    file_handler = logging.FileHandler(settings.LOG_FILE)
    file_formatter = jsonlogger.JsonFormatter(
        '%(asctime)s %(request_id)s %(name)s %(levelname)s %(message)s',
        rename_fields={"levelname": "level", "asctime": "timestamp"}
    )
    file_handler.setFormatter(file_formatter)
    file_handler.addFilter(RequestIDFilter())
    
    # 添加处理器
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)
    
    return logger


# 初始化日志
logger = setup_logger()


class LoggingMiddleware(BaseHTTPMiddleware):
    """日志中间件，记录请求和响应"""
    async def dispatch(
        self, request: Request, call_next: RequestResponseEndpoint
    ) -> Response:
        # 生成或获取请求ID
        request_id = request.headers.get("X-Request-ID")
        if not request_id:
            import uuid
            request_id = str(uuid.uuid4())
        
        # 将请求ID添加到请求状态
        request.state.request_id = request_id
        
        # 记录请求信息
        start_time = datetime.now()
        logger.info(
            f"Request: {request.method} {request.url}",
            extra={"request_id": request_id}
        )
        
        try:
            # 处理请求
            response = await call_next(request)
            
            # 记录响应信息
            process_time = (datetime.now() - start_time).total_seconds()
            logger.info(
                f"Response: {response.status_code} (took {process_time:.3f}s)",
                extra={"request_id": request_id}
            )
            
            # 添加请求ID到响应头
            response.headers["X-Request-ID"] = request_id
            return response
        except Exception as e:
            # 记录异常
            logger.error(
                f"Request failed: {str(e)}",
                exc_info=True,
                extra={"request_id": request_id}
            )
            raise
